import json
import os
import yaml
from itertools import islice
from bs4 import BeautifulSoup
import requests
import time
import random


def read_config() -> dict:
    '''
    读取配置文件
    '''
    config_path = os.path.join(os.path.dirname(__file__), 'config.yaml')
    with open(config_path, 'r', encoding='utf-8') as f:
        config = yaml.load(f, Loader=yaml.FullLoader)
        return config


config = read_config()
codesign_config = config['codesign']

TOKEN = codesign_config.get('token')
# 轮询次数限制 (次) 到次数会暂停
POLLING_CYCLE = 12
CURRENT_POLLING_CYCLE = 0
# 轮询等待时间 (s)
POLLING_CYCLE_WAIT_TIME = 50

'''
请求时的头部信息
'''
HEADERS = {
    'Origin': 'https://codesign.qq.com',
    'Referer': 'https://codesign.qq.com',
    'Content-Type': 'application/json;charset=UTF-8',
    'Accept': 'application/json, text/plain, */*',
    'Authorization': 'Bearer ' + TOKEN,
}


def get_icon_list_from_remote_in_codesign():
    """
    获取codesign上的icon列表
    """
    # 获取icon列表的url
    url = codesign_config['icon_list_url']
    per_page = codesign_config['per_page']
    print(url)
    # 获取icon列表的请求参数
    project_id = codesign_config['project_id']
    params = {
        'project_id': project_id,
        'include': 'creator',
        'per_page': per_page,
        'page': 1
    }
    # 发送请求
    response = requests.get(url, params=params, headers=HEADERS)
    # 获取响应数据
    response_data = response.json()
    # 获取icon列表
    icon_list = response_data['data']
    print('获取到{}个icon'.format(len(icon_list)))
    return icon_list


retry_count_dict = {

}


def read_json_file(json_path):
    '''
    读取的json文件并加载
    '''
    # 读json文件
    with open(json_path, 'r', encoding='utf-8') as f:
        # 装载数据
        json_data = json.load(f)
        return json_data
def batch_delete_icons(icon_list):
    '''
    批量删除icon
    '''
    icon_id_list = list(map(lambda x: x['id'], icon_list))
    delete_json_data = json.dumps({
        'icon': icon_id_list
    })
    print(delete_json_data);
    response = requests.request(
        'DELETE', codesign_config['request_url'], headers=HEADERS)
    # print(response.json())
    return response;

def update_icon_in_codesign(icon_id, update_key_value_dict: dict):
    '''
    更新codesig上的icon
    '''
    time.sleep(random.randint(0, 2))
    if(CURRENT_POLLING_CYCLE > POLLING_CYCLE):
        print('轮询次数超过{}次，暂停{}s'.format(POLLING_CYCLE, POLLING_CYCLE_WAIT_TIME))
        time.sleep(POLLING_CYCLE_WAIT_TIME)
        CURRENT_POLLING_CYCLE = 0
    update_request_url = codesign_config.get('update_request_url')
    update_request_method = codesign_config.get(
        'update_request_method')

    for key in update_key_value_dict.keys():
        print('更新{}为{}'.format(key, update_key_value_dict[key]))

    update_json_data = json.dumps(update_key_value_dict)
    print(update_json_data)
    response = requests.request(update_request_method.lower(
    ), update_request_url.replace('{icon_id}', icon_id), headers=HEADERS, data=update_json_data)
    if 'message' in response.json():
        write_error_log('codesign>>icon_id:{}更新出现错误：{}'.format(icon_id, response.json()['message']))
        print('更新{}出现错误：{},正在重试'.format(icon_id,response.json()['message']))
        time.sleep(random.randint(2, 8))
        retry_count = retry_count_dict.get(icon_id, 0)
        retry_count_dict.__setitem__(
            icon_id, retry_count+1)
        if retry_count > 5:
            print('重试次数超过5次，跳过')
            return response
        return update_icon_in_codesign(icon_id, update_key_value_dict)
    return response


def chunk_list(it, limit):
    """
    列表分块
    """
    it = iter(it)
    return iter(lambda: list(islice(it, limit)), [])


def save_icon_svg(icon_str, icon_save_path):
    '''
    保存icon的svg文件
    '''
    with open(icon_save_path, 'w', encoding='utf-8') as f:
        f.write(icon_str)
        f.close()


def create_icon_svg(icon_dict):
    '''
    创建一个icon的svg文件
    '''
    # 获取icon的id
    icon_id = icon_dict['icon_id']
    # 获取icon的viewbox
    viewbox = icon_dict['viewbox']
    # 获取icon的内容
    contents = icon_dict['contents']
    # 获取icon的高度
    height = icon_dict.get('height', None)
    # 获取icon的宽度
    width = icon_dict.get('width', None)
    # 创建一个svg对象
    svg = BeautifulSoup(features='lxml')
    # 创建一个svg标签
    svg_tag = svg.new_tag('svg')
    # 给svg标签添加 viewBox 属性
    svg_tag['viewBox'] = viewbox
    # 给svg标签添加 xmlns 属性
    svg_tag['xmlns'] = "http://www.w3.org/2000/svg"
    # 给svg标签添加 width height 属性
    if width:
        svg_tag['width'] = width
    if height:
        svg_tag['height'] = height
    # svg标签填充内容
    svg_tag.extend(contents)
    # 将svg标签添加到svg对象中
    svg.append(svg_tag)
    # 将svg对象转换成字符串
    svg_str = str(svg)
    return svg_str


def read_icon_font_json_dict(json_path):
    '''
    读取iconfont的json文件并生成字典
    '''
    # 读json文件
    with open(json_path, 'r', encoding='utf-8') as f:
        # 装载数据
        json_data = json.load(f)
        # 获取json文件中的glyphs
        glyphs = json_data['glyphs']
        css_prefix = json_data['css_prefix_text']
        # 构建快速icon字典
        icon_dict = {}
        # 遍历icon列表
        for json_icon in glyphs:
            # 获取icon的class名称
            font_class = json_icon['font_class']
            font_class = '{p}{c}'.format(p=css_prefix, c=font_class)
            # 获取icon的unicode
            icon_unicode = json_icon['unicode']
            # 获取icon unicode_decimal
            icon_unicode_decimal = json_icon['unicode_decimal']
            name = json_icon['name']
            # 将icon的名称和unicode添加到icon字典中
            icon_dict[font_class] = {
                'class': font_class,
                'name': name,
                'unicode': icon_unicode,
                'unicode_decimal': icon_unicode_decimal,
            }
        return icon_dict


def read_icon_font_cls_prefix(json_path)->str:
    '''
    读取 iconfont json配置得到icon的前缀
    '''
    json_data = read_json_file(json_path)
    return json_data['css_prefix_text']


def read_codesign_font_json_dict(json_path):
    '''
    读取codesign的json文件并生成字典
    '''
    # 读json文件
    with open(json_path, 'r', encoding='utf-8') as f:
        # 装载数据
        json_data = json.load(f)
        return json_data


def read_codesign_font_json_icons_dict(json_path):
    '''
    读取codesign的json文件并生成icons字典
    '''
    json_data = read_codesign_font_json_dict(json_path)
    # 获取json文件中的icons
    icons = json_data['icons']
    # 构建快速icon字典
    icon_dict = {}
    # 遍历icon列表
    for icon in icons:
        class_name = icon['class_name']
        unicode = icon['unicode']
        unicode_decimal = icon['unicode_decimal']
        name = icon['name']
        icon_dict[class_name] = {
            'class': class_name,
            'name': name,
            'unicode': unicode,
            'unicode_decimal': unicode_decimal
        }
    return icon_dict


def append_prefix_to_codesign_class_name(icon_dict, prefix):
    '''
    为codesign的icon添加前缀
    '''
    new_icon_dict = {}
    for key in icon_dict.keys():
        class_name = prefix + icon_dict[key]['class']
        icon_dict[key]['class'] = prefix + icon_dict[key]['class']
        new_icon_dict[class_name] = {**icon_dict[key], 'class': class_name}
    return new_icon_dict


def read_icon_font_js_to_svg(js_path, icon_font_config):
    '''
    读取iconfont的js拆分出svg文件
    '''
    with open(js_path, 'r', encoding='utf-8') as f:
        js_code = f.read()
        # 提取js代码中 单引号里面的内容
        svg = js_code.split("'")[1]
        # 将svg代码转换成BeautifulSoup对象
        svg = BeautifulSoup(svg, 'lxml')
        # 收集所有 symbol 标签
        symbols = svg.find_all('symbol')
        list1 = []
        # 遍历所有symbol标签
        for symbol in symbols:
            # 获取symbol标签的 id 属性值
            id = symbol.get('id')
            # 获取symbol标签的 viewBox 属性值
            viewBox = symbol.get('viewbox')
            # 获取symbol标签的 所有属性
            # 获取symbol标签内所有子元素
            content = symbol.contents
            # 将获取到的内容拼接成一个字典
            dict1 = {
                'icon_id': id,
                'viewbox': viewBox,
                'height': icon_font_config['out_svg_height'],
                'width': icon_font_config['out_svg_width'],
                'contents': content
            }

            # 将字典添加到列表中
            list1.append(dict1)
        return list1


def read_codesign_js_to_svg(js_path):
    """
    读取codesign的js文件并生成svg文件
    """
    with open(js_path, 'r', encoding='utf-8') as f:
        # 读取js文件
        js_str = f.read()
        # 获取svg字符串
        svg_str = js_str.split('<svg>')[1]
        svg_str = '<svg>'+svg_str
        # 将svg代码转换成BeautifulSoup对象
        svg = BeautifulSoup(svg_str, features='lxml')
        # 选中svg标签
        svg_tag = svg.select_one('svg')
        # 收集所有 symbol 标签
        symbol_tags = svg_tag.select('symbol')
        list1 = []
        for symbol_tag in symbol_tags:
            # 获取symbol标签的id
            symbol_id = symbol_tag['id']
            # 获取symbol标签的viewbox
            viewbox = symbol_tag['viewbox']
            # 获取symbol标签的内容
            contents = symbol_tag.contents
            # 获取symbol标签的高度
            height = symbol_tag['height']
            # 获取symbol标签的宽度
            width = symbol_tag['width']
            # 创建一个icon字典
            icon_dict = {
                'icon_id': symbol_id,
                'viewbox': viewbox,
                'contents': contents,
                'height': height,
                'width': width
            }
            # 将icon字典添加到列表中
            list1.append(icon_dict)
        return list1


def read_custom_js_to_svg(js_path, svg_rule_def, default_height=200, default_width=200):
    """
    读取自定义js文件拆分成svg文件
    """
    with open(js_path, 'r', encoding='utf-8') as f:
        # 读取js文件
        js_str = f.read()
        # 获取svg字符串
        svg_str = svg_rule_def(js_str)
        # 将svg代码转换成BeautifulSoup对象
        svg = BeautifulSoup(svg_str, features='lxml')
        # 选中svg标签
        svg_tag = svg.select_one('svg')
        # 收集所有 symbol 标签
        symbol_tags = svg_tag.select('symbol')
        list1 = []
        for symbol_tag in symbol_tags:
            # 获取symbol标签的id
            symbol_id = symbol_tag['id']
            # 获取symbol标签的viewbox
            viewbox = symbol_tag['viewbox']
            # 获取symbol标签的内容
            contents = symbol_tag.contents
            # 获取symbol标签的高度
            height = default_height
            # 获取symbol标签的宽度
            width = default_width
            # 创建一个icon字典
            icon_dict = {
                'icon_id': symbol_id,
                'viewbox': viewbox,
                'contents': contents,
                'height': height,
                'width': width
            }
            # 将icon字典添加到列表中
            list1.append(icon_dict)
        return list1


def filter_repeat_icon(origin_icon_list, icon_list):
    """
    根据svg过滤重复icon
    其中icon列表中每一个icon至少要拥有`icon_id`和 `contents` 两项
    """
    # 过滤掉重复的icon的id
    new_icon_list = filter(
        lambda x: x['icon_id'] not in origin_icon_list, icon_list)
    origin_icon_id_list = list(map(lambda x: x['icon_id'], origin_icon_list))
    # 重复的icon记录到错误日志
    repeat_icon_list = list(
        filter(lambda x: x['icon_id'] in origin_icon_id_list, icon_list))
    if len(repeat_icon_list) > 0:
        write_error_log('id重复的icon：{}'.format(
            ','.join(map(lambda x: x['icon_id'], repeat_icon_list))))
    origin_icon_contents_list = list(
        map(lambda x: x['contents'], origin_icon_list))

    # 过滤掉重复的icon的svg
    new_icon_without_repeat_id_list = filter(
        lambda x: x['contents'] not in origin_icon_contents_list, new_icon_list)
    new_icon_without_repeat_id_list = list(new_icon_without_repeat_id_list)
    # 重复的icon记录到错误日志
    repeat_icon_list = list(
        filter(lambda x: x['contents'] in origin_icon_contents_list, new_icon_list))
    if len(repeat_icon_list) > 0:
        write_error_log('svg重复的icon：{}'.format(
            ','.join(map(lambda x: x['icon_id'], repeat_icon_list))))
    return new_icon_without_repeat_id_list


def write_error_log(error):
    """
    写错误日志
    """
    error_log_path = os.path.join(os.path.dirname(__file__), 'error.log')
    with open(error_log_path, 'a', encoding='utf-8') as f:
        f.write(error)
        f.write('\n')
        f.close()
